/** @format */
import { isFunction, isString } from 'lodash'
type AsyncFunction = (...args: any[]) => Promise<any>

/**
 *  代理实例 -->控制服务中所有方法流程
 *
 * @param {*} serviceInstance
 * @return {*}
 */
export function createTopApiProxy(APIObject: object) {
  return new Proxy(APIObject, {
    get(instanceTarget, propKey, receiver) {
      // 是函数则代理
      if (isFunction(instanceTarget?.[propKey])) {
        return createTopApiMethodsProxy(instanceTarget?.[propKey], propKey as string)
      }
      return Reflect.get(instanceTarget, propKey, receiver)
    }
  })
}

function createTopApiMethodsProxy(method: AsyncFunction, methodName: string) {
  return new Proxy(method, {
    apply(target, object, args) {
      const startTopAPItime = Date.now()
      const result = Reflect.apply(target, object, args)
      const context = args[0]
      const isAsyncFn = result instanceof Promise

      if (isAsyncFn) {
        result?.then(res => {
          const endTopAPItime = Date.now()
          context?.logger?.info('TopApilog', methodName, `${endTopAPItime - startTopAPItime}ms`, args, res)
        })
      }
      return result
    }
  })
}

export function createBaseDaoProxy(baseDaoInstance: any, context) {
  return new Proxy(baseDaoInstance, {
    get(instanceTarget, propKey, receiver) {
      // 是函数则代理
      if (isFunction(instanceTarget?.[propKey])) {
        return createBaseDaoMethodsProxy(instanceTarget?.[propKey], propKey as string, instanceTarget, context)
      }
      return Reflect.get(instanceTarget, propKey, receiver)
    }
  })
}

function createBaseDaoMethodsProxy(method: AsyncFunction, methodName: string, instanceTarget: any, context: any) {
  return new Proxy(method, {
    apply(target, object, args) {
      const startSQLtime = Date.now()
      const result = Reflect.apply(target, object, args)
      const isAsyncFn = result instanceof Promise
      if (isAsyncFn) {
        result?.then(res => {
          const endSQLtime = Date.now()
          console.log(endSQLtime,'endSQLtimeendSQLtimeendSQLtime')
          if (methodName !== 'aggregate') {
            context?.logger?.info(
              'SQLlog',
              `${instanceTarget.dbName}`,
              methodName,
              `${endSQLtime - startSQLtime}ms`,
              args,
              res
            )
          }
        })
      }
      return result
    }
  })
}
